import { BoundingSphere, Cartesian3, Rectangle } from "cesium";
import { tagOptions } from "./options";
import { lngLatsToCartesian3s } from "./../utils/coordinate";

export const toTagByInfo = ({ position: location }, camera) => {
  if (!location) return Promise.reject();
  location = JSON.parse(location);
  const { cameraView, position } = location;
  if (!cameraView && !position) return Promise.reject();
  let destination, orientation;
  if (cameraView) {
    destination = cameraView.destination;
    orientation = cameraView.orientation;
  } else if (position) {
    destination = position;
  }
  return toTag({
    camera,
    destination,
    orientation,
  });
};

export const toTag = ({ destination, orientation, camera }) => {
  return new Promise((resolve, reject) => {
    if (!destination || !camera) {
      reject();
      return;
    }
    const { lng, lat, height } = destination;
    const { heading, pitch, roll } = orientation || {};
    if (![lng, lat, heading, pitch, roll].includes(undefined)) {
      camera.flyTo({
        destination: Cartesian3.fromDegrees(lng, lat, height || 0),
        orientation,
        complete: () => {
          resolve(destination);
        },
      });
    } else if (![lng, lat].includes(undefined)) {
      const bs = new BoundingSphere(
        Cartesian3.fromDegrees(lng, lat, height || 0),
        40
      );
      camera.flyToBoundingSphere(bs, {
        complete: () => {
          resolve(destination);
        },
      });
    } else {
      reject();
    }
  });
};

export const toPoints = ({
  lnglatArr = [],
  camera,
  flyOptions = {},
  zoomCoefficient = 1.1,
  minheight = 100,
}) => {
  if (!camera || !lnglatArr) return Promise.reject();
  return new Promise((resolve) => {
    const bs = BoundingSphere.fromPoints(
      lnglatArr.map((i) => {
        return Cartesian3.fromDegrees(i.lng, i.lat, 0);
      })
    );
    bs.radius *= zoomCoefficient;
    bs.radius < minheight ? (bs.radius = minheight) : false;
    camera.flyToBoundingSphere(bs, {
      offset: {
        heading: 0,
        pitch: -Math.PI / 2,
        roll: 0,
      },
      maximumHeight: bs.radius,
      ...flyOptions,
      complete: resolve,
    });
  });
};

export const toPointsRange = ({
  lnglatArr = [],
  camera,
  flyOptions = {},
  zoomCoefficient = 1.1,
  minheight = 100,
}) => {
  if (!camera || !lnglatArr) return Promise.reject();
  let e = 0,
    n = 90,
    s = 0,
    w = 200;
  lnglatArr.forEach(({ lng, lat }) => {
    if (lng > e) e = lng;
    if (lng < w) w = lng;
    if (lat < n) n = lat;
    if (lat > s) s = lat;
  });
  const rectangle = Rectangle.fromDegrees(w, s, e, n);
  let { west, south, east, north, width, height } = rectangle;
  const newHeight = height * zoomCoefficient;
  const newWidth = width * zoomCoefficient;
  const lngdiff = (newWidth - width) / 2;
  const latdiff = (newHeight - height) / 2;
  rectangle.west = west - lngdiff;
  rectangle.east = east + lngdiff;
  rectangle.north = north + latdiff;
  rectangle.south = south - latdiff;

  return new Promise((resolve) => {
    camera.flyTo({
      destination: rectangle,
      orientation: {
        heading: 0,
        pitch: -Math.PI / 2,
        roll: 0,
      },
      ...flyOptions,
      complete: resolve,
    });
  });
};

export const billboardFromTagInfo = (tagInfo, options = {}) => {
  let position = {};
  let positionData = {};
  if (tagInfo.position) positionData = JSON.parse(tagInfo.position);
  if (positionData.position) {
    position = positionData.position;
  } else {
    position = positionData;
  }

  return tagOptions({
    id: `tag_${tagInfo.id}`,
    tag: {
      color: tagInfo.color,
      icon: tagInfo.icon,
      text: tagInfo.label,
    },
    rawData: tagInfo,
    positionData,
    position,
    ...options,
  });
};

export const getPersonObj = (obj = {}) => {
  obj ??= {};
  const output = {
    id: "",
    name: "",
    gender: "",
    age: "",
    idCard: "",
    phone: "",
    imageUri: "",
    address: "",
    nativePlace: "",
    nativeAddress: "",
    street: "",
    houseNumber: "",
    roomNumber: "",
    birth: "",
    positions: [],
  };
  Object.entries(obj).forEach(([key, value]) => {
    if (value) output[key] = value;
  });
  return output;
};
